﻿///////////////////////////////////////////////////////////////////////////////
//
// This file is part of the BassDrop project
//   https://code.google.com/p/bass-drop/
//
//
// Creator:	Gergely Krajcsovszki (krajcsovszkig@hotmail.com)
// Date:	2014-05-04 11:45
//
//
// Copyright © 2013-2014. Gergely Krajcsovszki
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//   http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
///////////////////////////////////////////////////////////////////////////////
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using BassDrop.Core.Common.Exceptions;

namespace BassDrop.Core.Common.Media.Playlists
{
	/// <summary>
	/// Wrapper class for placing media tracks in playlists
	/// </summary>
	public class PlaylistItemMediaTrack : PlaylistItemBase
	{
		/// <summary>
		/// The referenced mediatrack
		/// </summary>
		public MediaTrack Track
		{
			get;
			private set;
		}

		/// <summary>
		/// Gets the length of the track in milliseconds
		/// 
		/// Null if the length is indeterminate
		/// </summary>
		public override long? Length
		{
			get
			{
				return Track.Length;
			}
		}

		/// <summary>
		/// Gets the unique ID of the referenced track in the media library.<para/>
		/// Id >= 1001<para/>
		/// Tracks that are not in the library have a null ID.<para/>
		/// </summary>
		public override long? LibraryId
		{
			get
			{
				return Track.LibraryId;
			}
		}

		/// <summary>
		/// Error occured while handling the item
		/// </summary>
		public override Exception Error
		{
			get
			{
				return Track.Error;
			}

			set
			{
				Track.Error = value;
			}
		}

		/// <summary>
		/// A mediaplayer that can play this item
		/// 
		/// Null if none found
		/// </summary>
		public override MediaDecoderBase MediaPlayer
		{
			get
			{
				return Track.MediaPlayer;
			}
		}

		/// <summary>
		/// Constructs a new playlist item for the passed mediatrack
		/// </summary>
		/// <param name="track"></param>
		public PlaylistItemMediaTrack( MediaTrack track )
		{
			Track = track;

			Track.PropertyChanged += Track_PropertyChanged;

			UpdatePlaystate();
		}

		/// <summary>
		/// Immediately starts playback of the track on the attached player from the beginning
		/// </summary>
		public override void Play()
		{
			if ( CurrentPlayState != PlayState.Playing && CurrentPlayState != PlayState.Initializing )
			{
				if ( MediaPlayer != null )
				{
					try
					{
						MediaPlayer.Track = this;
						MediaPlayer.Play();
					}
					catch ( Exception e )
					{
						Error = e;
						CurrentPlayState = PlayState.Error;
					}
				}
				else if ( Track.FilePath == null )
				{
					Error = new MissingMediaException();
					CurrentPlayState = PlayState.Error;
				}
				else
				{
					Error = new FormatNotSupportedException( Track.FileExtension, (Track.FilePath != null ? Track.FilePath.ToString() : "") );
					CurrentPlayState = PlayState.Error;
				}
			}
		}

		/// <summary>
		/// Sets this track as the currently played on the attached player and pauses it
		/// </summary>
		public override void Pause()
		{
			if ( CurrentPlayState != PlayState.Initializing )
			{
				if ( MediaPlayer != null )
				{
					try
					{
						MediaPlayer.Track = this;
						MediaPlayer.Pause();
					}
					catch ( Exception e )
					{
						Error = e;
						CurrentPlayState = PlayState.Error;
					}
				}
				else
				{
					Error = new FormatNotSupportedException( Track.FileExtension, Track.FilePath.ToString() );
					CurrentPlayState = PlayState.Error;
				}
			}
		}

		/// <summary>
		/// Stops the attached player if this is its current track
		/// </summary>
		public override void Stop()
		{
			if ( MediaPlayer != null && MediaPlayer.Track == this )
			{
				MediaPlayer.Stop();
			}
		}

		/// <summary>
		/// Resets the position of this track to the beginning. Doesn't change play state
		/// </summary>
		public override void Reset()
		{
			if ( MediaPlayer != null && MediaPlayer.Track == this )
			{
				MediaPlayer.Position = 0;
			}
		}

		/// <summary>
		/// Creates a copy of this object. The copy is shallow in this implementation.
		/// The Parent and Selected properties are not copied.
		/// </summary>
		/// <returns></returns>
		public override PlaylistItemBase Clone()
		{
			return new PlaylistItemMediaTrack( Track );
		}

		private void UpdatePlaystate()
		{
			if ( Track.Error != null )
			{
				CurrentPlayState = PlayState.Error;
			}
			else
			{
				if ( !Track.IsInitialized )
				{
					CurrentPlayState = PlayState.Initializing;
				}
				else if ( CurrentPlayState == PlayState.Error || CurrentPlayState == PlayState.Initializing )
				{
					CurrentPlayState = PlayState.Stopped;
				}
			}
		}

		private void Track_PropertyChanged( object sender, System.ComponentModel.PropertyChangedEventArgs e )
		{
			if ( e.PropertyName == "Error" || e.PropertyName == "IsInitialized" )
			{
				UpdatePlaystate();
			}

			OnPropertyChanged( e );
		}
	}
}
